package cn.edu.dutir.utility;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class StreamUtil {

	public static final int IO_NO = 0;
	public static final int IO_READ = 1;
	public static final int IO_WRITE = 2;
	public static final int IO_RDWT = 3;

	public static final int DEFAULT_BUFFER_SIZE = 1024 * 10;
	public static final String lineSeparator = System
			.getProperty("line.separator");

	private Writer writer = null;
	private BufferedReader reader = null;
	private int mode = 0;

	private StreamUtil() {
		this(0);
	}

	private StreamUtil(int mode) {
		this.mode = mode;
	}

	public static StreamUtil streamUtil() {
		return new StreamUtil();
	}

	public static StreamUtil fileReader() {
		return new StreamUtil(IO_READ);
	}

	public static StreamUtil fileReader(String filename) {
		return fileReader(new File(filename));
	}

	public static StreamUtil fileReader(File file) {
		StreamUtil su = new StreamUtil(IO_READ);
		su.setFileReader(file);
		return su;
	}

	public static StreamUtil fileReader(Reader reader) {
		StreamUtil su = new StreamUtil(IO_READ);
		su.setReader(reader);
		return su;
	}

	public static StreamUtil fileWriter() {
		return new StreamUtil(IO_WRITE);
	}

	public static StreamUtil fileWriter(String filename) {
		return fileWriter(new File(filename));
	}

	public static StreamUtil fileWriter(File file) {
		StreamUtil su = new StreamUtil(IO_WRITE);
		su.setFileWriter(file);
		return su;
	}

	public static StreamUtil fileWriter(Writer writer) {
		StreamUtil su = new StreamUtil(IO_WRITE);
		su.setWriter(writer);
		return su;
	}

	public void flush() throws IOException {
		writer.flush();
	}
	
	public void setWriter(Writer w) {
		if (writer != null) {
			try {
				writer.flush();
				writer.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		writer = w;
		mode |= IO_WRITE;
	}

	public Writer getWriter() {
		return writer;
	}

	public void setReader(Reader r) {
		if (reader != null) {
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		if (r instanceof BufferedReader) {
			reader = (BufferedReader) r;
		} else {
			reader = new BufferedReader(reader);
		}
		mode |= IO_READ;
	}

	public Reader getReader() {
		return reader;
	}

	public void setFileWriter(String filename) {
		setFileWriter(new File(filename));
	}

	public void setFileWriter(File file) {
		try {
			setWriter(new FileWriter(file));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setFileReader(String filename) {
		setFileReader(new File(filename));
	}

	public void setFileReader(File file) {
		try {
			setReader(new BufferedReader(new FileReader(file)));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public int mode() {
		return mode;
	}

	public void close() throws IOException {
		if (writer != null) {
			writer.close();
			writer = null;
		}
		if (reader != null) {
			reader.close();
			reader = null;
		}
		mode = IO_NO;
	}

	public void writeln(String str) throws IOException {
		writer.write(str + lineSeparator);
	}

	public void write(String str) throws IOException {
		writer.write(str);
	}
	
	public String readLine() throws IOException {
		return reader.readLine();
	}

	public int read(char cbuf[]) throws IOException {
		return reader.read(cbuf);
	}
	
	public int read(char cbuf[], int off, int len) throws IOException {
		return reader.read(cbuf, off, len);
	}
	
	public String readContent() throws IOException {
		return readContent(DEFAULT_BUFFER_SIZE);
	}

	/**
	 * Read the whole content from specified stream
	 * @param bufferSize buffer size used for buffered stream
	 * @return the content read from stream
	 * @throws IOException
	 */
	public String readContent(int bufferSize) throws IOException {
		char buffer[] = new char[bufferSize];
		String content = "";
		int len = reader.read(buffer);
		while (len > 0) {
			content += new String(buffer, 0, len);
			len = reader.read(buffer);
		}
		return content;
	}
}
